from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import insert,select,update,delete
from sqlalchemy.orm import declarative_base
from sqlalchemy.dialects.mysql import insert as mysql_insert

Base = declarative_base()

class BaseModel(Base):
    __abstract__ = True

    @classmethod
    async def create(cls,session: AsyncSession,**kwargs):
        obj = cls(**kwargs)
        session.add(obj)
        await session.commit()
        await session.refresh(obj)
        return obj

    @classmethod
    async def get(cls, session: AsyncSession, **filters):
        obj = select(cls).filter_by(**filters)
        result = await session.execute(obj)
        return result.scalar_one_or_none()

    @classmethod
    async def update(cls, session: AsyncSession, filters:dict,values:dict):
        stmt = update(cls).filter_by(**filters).values(**values)
        await session.execute(stmt)
        await session.commit()

    @classmethod
    async def delete(cls, session: AsyncSession, **filters):
        stmt = delete(cls).filter_by(**filters)
        await session.execute(stmt)
        await session.commit()

    @classmethod
    async def paginate(cls,session: AsyncSession,page:int=1,page_size:int=100,**filters):
        stmt = select(cls).filter_by(**filters).offset(page*page_size).limit(page_size)
        result = await session.execute(stmt)
        return result.scalars().all()

    @classmethod
    async def count(cls,session: AsyncSession,**filters):
        stmt = select(cls).filter_by(**filters)
        result = await session.execute(stmt)

    @classmethod
    async def bulk_insert_ignore(cls,session: AsyncSession, data_list:list[dict]):
        if not data_list:
            return
        stmt = mysql_insert(cls).values(data_list)
        # 获取所有字段，排除主键和创建时间类字段
        update_fields = {col.name: stmt.inserted[col.name]
                         for col in cls.__table__.columns
                         if col.name not in ('id', 'created_at', 'created_by')}
        stmt = stmt.on_duplicate_key_update(**update_fields)
        # stmt = stmt.on_duplicate_key_update(
        #     **{k:stmt.inserted[k] for k in stmt.inserted.keys()}
        # )
        try:
            await session.execute(stmt)
            await session.commit()
        except Exception as e:
            await session.rollback()
            raise RuntimeError(f"批量插入失败: {e}")